﻿using ExcelAutomator.Configuration;
using ExcelAutomator.Validation;
using Microsoft.Office.Interop.Excel;

namespace ExcelAutomator.Executors.Range
{
	[Executor(ExecutorName, ExecutorType, ExecutorAction)]
	internal class RangeCopyExecutor : Executor<RangeConfiguration>
	{
		public const string ExecutorName = "Range Copy Executor";
		public const string ExecutorType = "range";
		public const string ExecutorAction = "copy";

		public override ExecutionResult OnExecute(ExecutionContext context)
		{
			Worksheet inputWs;
			Worksheet targetWs;

			if (context.InputWorkbook.TryGetWorksheet(Configuration.SourceAddress, out inputWs) &&
				  context.TargetWorkbook.TryGetWorksheet(Configuration.TargetAddress, out targetWs))
			{
				var sourceRange = inputWs.get_Range(Configuration.SourceAddress, System.Type.Missing);
				sourceRange.Copy(System.Type.Missing);

				var targetRange = targetWs.get_Range(Configuration.TargetAddress, System.Type.Missing);

				if (!Configuration.RowHeight.IsNOE())
				{
					targetWs.get_Range(Configuration.SourceAddress, System.Type.Missing).RowHeight = Configuration.RowHeight;
				}

				targetRange.PasteSpecial(XlPasteType.xlPasteAll, XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);

				return
					ExecutionResult.CreateSuccess(
						string.Format("Copy '{0}' -> '{1}'", Configuration.SourceAddress, Configuration.TargetAddress), context);
			}
			return ExecutionResult.CreateFailure("Either the source or target workseet doesn't exists.", context);
		}

		public override void OnConfigure(string xmlConfig, out RangeConfiguration configuration)
		{
			configuration = ConfigurationBuilder.Build<RangeConfiguration>(xmlConfig, Constants.ExecutorExtensionsNamespace);
		}

		public override void OnValidate(ValidationEngine validationEngine, ExecutionContext context)
		{
			validationEngine.Validate.That.String(Configuration.SourceAddress, RangeConfiguration.SourceAddressAttributeName)
				.IsNotNullOrEmpty();

			validationEngine.Validate.That.String(Configuration.TargetAddress, RangeConfiguration.TargetAddressAttributeName)
				.IsNotNullOrEmpty();

			validationEngine.Validate.That.Reflected(Configuration)
				.PropertyValuesContainNot("%");

			validationEngine.Validate.That.Excel(context.InputWorkbook)
				.WorksheetPreFixIsDefined(Configuration.SourceAddress);

			validationEngine.Validate.That.Excel(context.TargetWorkbook)
				.WorksheetPreFixIsDefined(Configuration.TargetAddress);

			validationEngine.Validate.That.Excel(context.InputWorkbook)
				.WorksheetExists(Configuration.SourceAddress);

			validationEngine.Validate.That.Excel(context.TargetWorkbook)
				.WorksheetExists(Configuration.TargetAddress);
		}

		public override string Name
		{
			get
			{
				return ExecutorName;
			}
		}

		public override string Type
		{
			get
			{
				return ExecutorType;
			}
		}

		public override string ActionId
		{
			get
			{
				return ExecutorAction;
			}
		}
	}
}
